package com.webull.information.center.mam;

import java.beans.PropertyVetoException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import javax.sql.DataSource;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.webull.information.center.carwler.common.util.NewsTaskUtil;
import com.webull.securities.client.model.Exchange;

public class GoogleMissss {
	protected final Logger logger = LogManager.getLogger(getClass());
	private static final RowMapper<ExchangeGG> exchangeRM = BeanPropertyRowMapper.newInstance(ExchangeGG.class);
	private static final RowMapper<ZzYgTickerMiss> zzYgTickerMissRM = BeanPropertyRowMapper
			.newInstance(ZzYgTickerMiss.class);

	public static void main(String[] args) throws PropertyVetoException {
		GoogleMissss miss = new GoogleMissss();
		miss.process(0);
	}


	public void process(int lastId) {

		ThreadPoolTaskExecutor ttt = new ThreadPoolTaskExecutor();
		ttt.setMaxPoolSize(40);
		ttt.initialize();

		do {
			List<ZzYgTickerMiss> query = query(lastId);
			if (query == null || query.isEmpty())
				break;

			lastId = query.get(query.size() - 1).getId();

			NewsTaskUtil.multiThreadProcess(query, this::process0, ttt);

			System.out.println("currentdate--->" + new Date() + ";lastId ---->" + lastId);
		} while (true);

		ttt.destroy();
	}

	private void process0(ZzYgTickerMiss miss) {
		Integer target = checkStock(miss.getSymbol(), miss.getExchangeCode());
		if (target != null) {
			back(miss.getId(), target, 2);
			return;
		}
		// 印度上报可能是反的
		if ("BOM".equalsIgnoreCase(miss.getSymbol()) && ("" + miss.getExchangeCode()).matches("\\d*")) {
			target = checkStock(miss.getExchangeCode(), miss.getSymbol());
			if (target != null) {
				back(miss.getId(), target, 2);
				return;
			}
		}

		target = checkFund(miss.getSymbol(), miss.getExchangeCode());
		if (target != null) {
			back(miss.getId(), target, 3);
			return;
		}
		target = checkMappingTable(miss.getSymbol(), miss.getExchangeCode());
		if (target != null) {
			back(miss.getId(), target, null);
			return;
		}
	}


	private Integer checkStock(String inputSm, String inputEx) {
		if (StringUtils.isBlank(inputSm))
			return null;

		if ("HKG".equalsIgnoreCase(inputEx))
			inputSm = StringUtils.leftPad(inputSm, 5, "0");

		List<Integer> exIds = genExchangeIds(inputEx);
		if (exIds != null && !exIds.isEmpty()){
			Map<String, Object> paramMap = new HashMap<>();
			paramMap.put("symbol", inputSm);
			paramMap.put("exIds", exIds);
			List<Integer> queryForList = prdNpJdbcTemplate
					.queryForList("select ticker_id from wl_securities.wls_stock where del =0 "
				+ " and (symbol = :symbol or exhibition_symbol = :symbol) "
							+ " and exchange_id in (:exIds)", paramMap, Integer.class);
			if (queryForList != null && !queryForList.isEmpty())
				return queryForList.get(0);
		}
		
		return null;
	}

	private Integer checkFund(String inputSm, String inputEx) {
		if (StringUtils.isBlank(inputSm))
			return null;

		if ("HKG".equalsIgnoreCase(inputEx))
			inputSm = StringUtils.leftPad(inputSm, 5, "0");

		List<Integer> exIds = genExchangeIds(inputEx);
		if (exIds != null && !exIds.isEmpty()) {
			Map<String, Object> paramMap = new HashMap<>();
			paramMap.put("symbol", inputSm);
			paramMap.put("exIds", exIds);
			List<Integer> queryForList = prdNpJdbcTemplate
					.queryForList("select ticker_id from wl_securities.wls_fund where del =0 "
							+ " and  symbol = :symbol" + " and exchange_id in (:exIds)", paramMap, Integer.class);
			if (queryForList != null && !queryForList.isEmpty())
				return queryForList.get(0);
		}

		return null;
	}

	private Integer checkMappingTable(String inputSm, String inputEx) {
		List<String> codes = genExchangeCodes(inputEx);
		if (codes != null && !codes.isEmpty()) {
			Map<String, Object> paramMap = new HashMap<>();
			paramMap.put("symbol", inputSm);
			paramMap.put("exCodes", codes);
			List<Integer> queryForList = prdNpJdbcTemplate
					.queryForList("select ticker_id from wl_app.wla_yg_ticker_map where del =0 " //
							+ " and  symbol = :symbol "
							+ " and exchange_code in (:exCodes)", paramMap, Integer.class);
			if (queryForList != null && !queryForList.isEmpty())
				return queryForList.get(0);
		}
		return null;
	}

	private List<ZzYgTickerMiss> query(Integer lastId) {
		return devJdbcTemplate.query(
				"select * from wl_search.wla_zz_yg_ticker_miss where id > ? order by id asc limit 100",
				zzYgTickerMissRM,
				lastId);
	}

	private void back(Integer id, Integer targetId, Integer type) {
		devJdbcTemplate.update("update wl_search.wla_zz_yg_ticker_miss set ticker_id = ?,ticker_type=? where id = ?",
				targetId, type, id);
	}

	/**
	 * 获取疑似匹配的所有交易所Id
	 * 
	 * @param inputEx
	 * @return
	 */
	private List<Integer> genExchangeIds(String inputEx) {

		List<Integer> res = new ArrayList<>();

		if (StringUtils.isBlank(inputEx))
			return res;
		for (ExchangeGG gg : exchangeGGs) {
			if (equalsIgsAny(inputEx, gg.getAlias(), gg.getGoogleCode(), gg.getExchangeCode(),
					gg.getExhibitionCode())) {
				res.add(gg.getId());

			}
		}
		return res;
	}

	private List<String> genExchangeCodes(String inputEx) {
		
		List<String> ggres = new ArrayList<>();

		if (StringUtils.isBlank(inputEx))
			return ggres;
		for (ExchangeGG gg : exchangeGGs) {
			if (equalsIgsAny(inputEx, gg.getAlias(), gg.getGoogleCode(), gg.getExchangeCode(),
					gg.getExhibitionCode())) {
				Optional.ofNullable(gg.getGoogleCode()).ifPresent(v -> ggres.add(v));
			}
		}
		return ggres;
	}

	private static boolean equalsIgsAny(String input, String... anys) {
		for (String any : anys) {
			if (StringUtils.equalsIgnoreCase(input, any))
				return true;
		}
		return false;
	}

	private List<ExchangeGG> getExchangeGG() {
		List<ExchangeGG> query2 = prdJdbcTemplate.query("select * from wl_securities.wls_exchange where del = 0",
				exchangeRM);

		for (ExchangeGG gg : query2) {
			String str = prdJdbcTemplate.queryForObject(
					"select max(exchange_code) from  wl_securities.wls_exchange_mapping where source_type = 3 and exchange_id = ? and del = 0",
					String.class, gg.getId());
			gg.setGoogleCode(str);
		}
		logger.info("exchangeGGs.size:{}", query2.size());
		return query2;
	}


	private final DataSource devDs = getDevDs();
	private final JdbcTemplate devJdbcTemplate = new JdbcTemplate(devDs);


	private final DataSource prdDs = getprdDs();
	private final JdbcTemplate prdJdbcTemplate = new JdbcTemplate(prdDs);
	private final NamedParameterJdbcTemplate prdNpJdbcTemplate = new NamedParameterJdbcTemplate(prdDs);

	private final List<ExchangeGG> exchangeGGs = getExchangeGG();

	private static DataSource getDevDs() {
		try {
			ComboPooledDataSource ds0 = new ComboPooledDataSource();
			ds0.setJdbcUrl(
					"jdbc:mysql://192.168.40.203:3306?useUnicode=true&characterEncoding=utf8&useSSL=false&rewriteBatchedStatements=true&zeroDateTimeBehavior=convertToNull&useTimezone=true");
			ds0.setDriverClass("com.mysql.jdbc.Driver");
			ds0.setUser("dev");
			ds0.setMaxPoolSize(20);
			ds0.setPassword("dev");
			return ds0;
		} catch (Exception e) {
			return null;
		}
	}

	private static DataSource getprdDs() {
		try {
			ComboPooledDataSource ds0 = new ComboPooledDataSource();
			ds0.setJdbcUrl(
					"jdbc:mysql://127.0.0.1:3399?useUnicode=true&characterEncoding=utf8&useSSL=false&rewriteBatchedStatements=true&zeroDateTimeBehavior=convertToNull&useTimezone=true");
			ds0.setDriverClass("com.mysql.jdbc.Driver");
			ds0.setUser("readonly");
			ds0.setMaxPoolSize(20);
			ds0.setPassword("readonly");
			return ds0;
		} catch (Exception e) {
			return null;
		}
	}

	public static class ExchangeGG extends Exchange {

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		/**
		 * 
		 */

		private String googleCode;

		public String getGoogleCode() {
			return googleCode;
		}

		public void setGoogleCode(String googleCode) {
			this.googleCode = googleCode;
		}

	}

	public static class ZzYgTickerMiss {

		private Integer id;
		private String symbol;
		private String exchangeCode;

		public Integer getId() {
			return id;
		}

		public void setId(Integer id) {
			this.id = id;
		}

		public String getSymbol() {
			return symbol;
		}

		public void setSymbol(String symbol) {
			this.symbol = symbol;
		}

		public String getExchangeCode() {
			return exchangeCode;
		}

		public void setExchangeCode(String exchangeCode) {
			this.exchangeCode = exchangeCode;
		}

	}
}
